import TodoEvent from "./TodoEvent";
import TodoDom from "./TodoDom";
//当一个变量对应有限的几个值时 要使用枚举： 方法分类
enum EVENT_TYPE {
    ADD = "add",
    REMOVE = "remove",
    TOGGLE = "toggle"
}
class Observer{
    private static instance: Observer;
    private oTodoList: HTMLElement;
    private todoEvent:TodoEvent;
    private todoDom:TodoDom;
    // 存放方法的容器
    private addHandlers:any[] = [];
    private removeHandlers:any[] = [];
    private toggleHandlers:any[] = [];

    constructor(oTodoList: HTMLElement){
        this.oTodoList = oTodoList;
        this.initTodo();
    }
    public static create(oTodoList:HTMLElement){
        if(!Observer.instance){
            Observer.instance = new Observer(oTodoList);
        }
        return Observer.instance;
    }

    // 初始化
    private initTodo(){
        this.todoEvent = new TodoEvent();
        this.todoDom = new TodoDom(this.oTodoList);
        for (const key in EVENT_TYPE) {
            this.initHandlers(EVENT_TYPE[key]);
        }
    }

    private initHandlers(type:EVENT_TYPE){
        switch(type){
            // 如果是ADD类型 就把添加的方法加入到存放添加方法的容器中
            case EVENT_TYPE.ADD:
                this.addHandlers.push(this.todoEvent.addTodo.bind(this.todoEvent)); // 改变this指向始终指向自己的实例
                this.addHandlers.push(this.todoDom.addItem.bind(this.todoDom));
                break;
            case EVENT_TYPE.REMOVE:
                this.removeHandlers.push(this.todoEvent.removeTodo.bind(this.todoEvent));
                this.removeHandlers.push(this.todoDom.removeItem.bind(this.todoDom));
                break;
            case EVENT_TYPE.TOGGLE:
                this.toggleHandlers.push(this.todoEvent.toggleTodo.bind(this.todoEvent));
                this.toggleHandlers.push(this.todoDom.toggleItem.bind(this.todoDom));
                break;
            default:
                break;
        }
    }

    public notify<T>(type: string,param:T){
        let i:number = 0;
        let handlers:any = [];
        let res:any;
        switch(type){
            case EVENT_TYPE.ADD:
                handlers = this.addHandlers;
                break;
            case EVENT_TYPE.REMOVE:
                handlers = this.removeHandlers;
                break;
            case EVENT_TYPE.TOGGLE:
                handlers = this.toggleHandlers;
                break;
            default:
                break;
        }
        res = handlers[i](param);
        while(i< handlers.length - 1){
            i ++;
            res = res.then(param =>{
                return handlers[i](param);
            });

        }

    }

}
export default Observer;